﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPMS.Utility;
using SPMS.Utility.Storage;
using SPMS.Log.Utility;
using SPMS.Log.ObjectFormatter;

namespace SPMS.Log
{
    /// <summary>
    /// 日志上下文
    /// </summary>
    /// <remarks>定义了日志框架的上下文</remarks>
    /// <history>
    /// [zanezeng]               2009/10/12 13:35    创建
    /// </history>
    public static class LoggingContext
    {
        #region ---Public Method

        /// <summary>
        /// 获得所有的扩展属性
        /// </summary>
        /// <value>所有的扩展属性</value>
        /// <remarks>各个存储区的优先级别为线程静态、可继承线程静态和全局属性。例如，在三个存储区中都有名为“Key1”的属性，那么最终保存到日志条目中的属性值为线程静态存储区存储的属性值</remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 11:46    创建
        /// </history>
        public static ICollection<KeyValuePair<string, object>> GetAllExtendedProperties()
        {
            //创建属性字典
            Dictionary<string, object> properties = new Dictionary<string, object>( s_GlobalProperties );

            //获得扩展属性
            Dictionary<string, object> inheritableProperties = s_InheritableStorage.GetData( KEY_INHERITABLETHREADPROPERTIES ) as Dictionary<string, object>;

            //判断扩展属性是否创建
            if (null != inheritableProperties)
            {
                //循环添加扩展属性
                foreach (KeyValuePair<string, object> item in inheritableProperties)
                {
                    //添加属性
                    properties[item.Key] = item.Value;
                }
            }

            //判断是否有线程静态扩展属性
            if (null != s_ThreadProperties)
            {
                //循环添加扩展属性
                foreach (KeyValuePair<string, object> item in s_ThreadProperties)
                {
                    //添加属性KD
                    properties[item.Key] = item.Value;
                }
            }

            //返回结果
            return (ICollection<KeyValuePair<string, object>>)properties;
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得全局日志扩展属性
        /// </summary>
        /// <value>日志扩展属性</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/30 16:40    创建
        /// </history>
        public static IDictionary<string, object> GlobalProperties
        {
            get
            {
                //返回全局扩展属性
                return s_GlobalProperties;
            }
        }

        /// <summary>
        /// 获得线程静态日志扩展属性
        /// </summary>
        /// <value>线程静态日志扩展属性</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/30 16:41    创建
        /// </history>
        public static IDictionary<string, object> ThreadProperties
        {
            get
            {
                //判断是否创建
                if (null == s_ThreadProperties)
                {
                    //如果没有创建，则创建
                    s_ThreadProperties = new Dictionary<string, object>();
                }

                //返回
                return s_ThreadProperties;
            }
        }

        /// <summary>
        /// 获得可继承线程静态扩展属性
        /// </summary>
        /// <value>可继承线程静态扩展属性</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 9:55    创建
        /// </history>
        public static IDictionary<string, object> InheritableThreadProperties
        {
            get
            {
                //获得扩展属性
                Dictionary<string, object> properties = s_InheritableStorage.GetData( KEY_INHERITABLETHREADPROPERTIES ) as Dictionary<string, object>;

                //判断扩展属性是否创建
                if (null == properties)
                {
                    //创建
                    properties = new Dictionary<string, object>();

                    //添加到存储器中
                    s_InheritableStorage.SetData( KEY_INHERITABLETHREADPROPERTIES, properties );
                }

                //返回
                return properties;
            }
        }

        /// <summary>
        /// 获得或者设置日志错误处理器
        /// </summary>
        /// <value>日志错误处理器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/25 15:34    创建
        /// </history>
        public static ILogErrorHandler ErrorHandler
        {
            get
            {
                //判断日志错误处理器是否设置
                if (null == s_ErrorHandler)
                {
                    //返回默认的日志错误处理器
                    return DefaultLogErrorHandler.Default;
                }

                //返回日志错误处理器
                return s_ErrorHandler;
            }
            set
            {
                //设置日志错误处理器
                s_ErrorHandler = value;
            }
        }

        /// <summary>
        /// 获得或者设置日志框架内容使用的元日志
        /// </summary>
        /// <value>日志框架内容使用的元日志</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 13:42    创建
        /// </history>
        public static Commons.Logging.ILog MetaLog
        {
            get
            {
                //判断是否设置了元日志
                if (null != s_MetaLog)
                {
                    //如果设置了元日志，则返回元日志
                    return s_MetaLog;
                }

                //默认返回默认元日志
                return DEFAULT_METALOG;
            }
            set
            {
                s_MetaLog = value;
            }
        }

        /// <summary>
        /// 获得全局的默认日志级别映射表
        /// </summary>
        /// <value>全局的默认日志级别映射表</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/7 17:34    创建
        /// </history>
        public static LevelMap DefaultLevelMap
        {
            get
            {
                //返回全局的默认日志级别映射表
                return s_DefaultLevelMap;
            }
        }

        /// <summary>
        /// 获得对象格式化器注册器
        /// </summary>
        /// <value>对象格式化器注册器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 14:35    创建
        /// </history>
        public static IObjectFormatterRegistry ObjectFormatterRegistry
        {
            get
            {
                return s_ObjectFormatterRegistry;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 全局扩展属性
        /// </summary>
        private static SynchronizedDictionary<string, object> s_GlobalProperties = new SynchronizedDictionary<string, object>();

        /// <summary>
        /// 线程静态扩展属性
        /// </summary>
        [ThreadStatic]
        private static Dictionary<string, object> s_ThreadProperties;

        /// <summary>
        /// 可继承线程静态存储器
        /// </summary>
        private static InheritableThreadLocalStorage s_InheritableStorage = new InheritableThreadLocalStorage();

        /// <summary>
        /// 对象格式化器注册表
        /// </summary>
        private static readonly ObjectFormatterRegistry s_ObjectFormatterRegistry = new ObjectFormatterRegistry();

        /// <summary>
        /// 全局的默认日志级别映射表
        /// </summary>
        private static LevelMap s_DefaultLevelMap = new LevelMap( true );

        /// <summary>
        /// 可继承线程静态扩展属性的键
        /// </summary>
        private const string KEY_INHERITABLETHREADPROPERTIES = "__INHERITABLETHREADPROPERTIES__";

        /// <summary>
        /// 日志框架内部错误处理器
        /// </summary>
        private volatile static ILogErrorHandler s_ErrorHandler;

        /// <summary>
        /// 元日志
        /// </summary>
        private volatile static Commons.Logging.ILog s_MetaLog;

        /// <summary>
        /// 默认的元日志
        /// </summary>
        private readonly static Commons.Logging.ILog DEFAULT_METALOG = Commons.Logging.SimpleLogFactory.Default.GetLog( "SPMS.Log" );

        #endregion
    }
}
